#include "Graphics.hpp"

using namespace luabind;
namespace bind
{
	namespace SL
	{
		namespace graphics
		{
			void BSpriteObject(lua_State* lua, const std::string& ns)
			{
				module(lua, ns.c_str())
					[
						class_<sl::SpriteObject, bases<sf::Sprite> >("SpriteObject")
							.def(constructor<>())
							.def(constructor<sf::Texture*>())
							.def("HasATexture", &sl::SpriteObject::HasATexture)
							.def("Update", &sl::SpriteObject::Update)
							.def("SetTexture", &sl::SpriteObject::SetTexture)
					];
			}

			void BFrameInfo(lua_State* lua, const std::string& ns)
			{
				module(lua, ns.c_str())
					[
						class_<sl::FrameInfo>("FrameInfo")
							.def(constructor<>())
							.def(constructor<unsigned int, unsigned int, const sf::Vector2i&>())
							.def("SetFrame", &sl::FrameInfo::SetFrame)
							.def("GetFrame", &sl::FrameInfo::GetFrame)
							.def("SetDelay", &sl::FrameInfo::SetDelay)
							.def("GetDelay", &sl::FrameInfo::GetDelay)
							.def("SetOffset", &sl::FrameInfo::SetOffset)
							.def("GetOffset", &sl::FrameInfo::GetOffset)
					];
			}

			void BAnimation(lua_State* lua, const std::string& ns)
			{
				module(lua, ns.c_str())
					[
						class_<sl::Animation, bases<sl::SpriteObject> >("Animation")
							.def(constructor<>())
							.def(constructor<sf::Texture*, const sf::Vector2i&>())
							.def(constructor<const sl::Animation&>())
							.scope
								[
									def("New", &sl::New<sl::Animation>)
								]
							.def("AddFrame", (sl::Animation*(sl::Animation::*)(const sl::FrameInfo&))&sl::Animation::AddFrame)
							.def("AddFrame", (sl::Animation*(sl::Animation::*)(unsigned int, unsigned int, const sf::Vector2i&))&sl::Animation::AddFrame)
							.def("SetSize", &sl::Animation::SetSize)
							.def("Start", &sl::Animation::Start)
							.def("Stop", &sl::Animation::Stop)
							.def("Pause", &sl::Animation::Pause)
							.def("Restart", &sl::Animation::Restart)
							.def("Update", &sl::Animation::Update)
							.def("IsRunning", &sl::Animation::IsRunning)
					];
			}

			void BDirection(lua_State* lua, const std::string& ns)
			{
				module(lua, ns.c_str())
					[
						class_<sl::Direction>("Direction")
							.def(constructor<>())
							.def(constructor<sl::Direction::Dir>())
							.def("SetDirection", &sl::Direction::SetDirection)
							.def("GetDirection", &sl::Direction::GetDirection)
							.def("ToString", &sl::Direction::ToString)
					];

				object dir = newtable(lua);
				dir["Up"] = sl::Direction::Up;
				dir["Down"] = sl::Direction::Down;
				dir["Left"] = sl::Direction::Left;
				dir["Right"] = sl::Direction::Right;
				dir["UpLeft"] = sl::Direction::UpLeft;
				dir["UpRight"] = sl::Direction::UpRight;
				dir["DownLeft"] = sl::Direction::DownLeft;
				dir["DownRight"] = sl::Direction::DownRight;
				globals(lua)[ns.c_str()]["Direction"]["Dir"] = dir;
			}

			void BDirAnimation(lua_State* lua, const std::string& ns)
			{
				module(lua, ns.c_str())
					[
						class_<sl::DirAnimation, bases<sl::Animation, sl::Direction> >("DirAnimation")
							.def(constructor<>())
							.def(constructor<const sl::Animation&>())
							.scope
								[
									def("New", &sl::New<sl::DirAnimation>)
								]
							.def("AddFrame", (sl::DirAnimation*(sl::DirAnimation::*)(const sl::FrameInfo&))&sl::DirAnimation::AddFrame)
							.def("AddFrame", (sl::DirAnimation*(sl::DirAnimation::*)(sl::Direction::Dir, const sl::FrameInfo&))&sl::DirAnimation::AddFrame)
							.def("AddFrame", (sl::DirAnimation*(sl::DirAnimation::*)(unsigned int, unsigned int, const sf::Vector2i&))&sl::DirAnimation::AddFrame)
							.def("AddFrame", (sl::DirAnimation*(sl::DirAnimation::*)(sl::Direction::Dir, unsigned int, unsigned int, const sf::Vector2i&))&sl::DirAnimation::AddFrame)
							.def("SetSize", &sl::DirAnimation::SetSize)
							.def("Start", &sl::DirAnimation::Start)
							.def("Stop", &sl::DirAnimation::Stop)
							.def("Pause", &sl::DirAnimation::Pause)
							.def("Restart", &sl::DirAnimation::Restart)
							.def("Update", &sl::DirAnimation::Update)
							.def("SetDirection", &sl::DirAnimation::SetDirection)
					];
			}

			void Bind(lua_State* lua, const std::string& ns)
			{
				open(lua);
				BSpriteObject(lua, ns);
				BFrameInfo(lua, ns);
				BAnimation(lua, ns);
				BDirection(lua, ns);
				BDirAnimation(lua, ns);
			}
		}
	}
}